package com.young.hzh_learning

import android.Manifest
import android.annotation.SuppressLint
import android.content.Context
import android.content.pm.PackageManager
import android.graphics.Color
import android.hardware.camera2.CameraCaptureSession
import android.hardware.camera2.CameraCharacteristics
import android.hardware.camera2.CameraDevice
import android.hardware.camera2.CameraManager
import android.media.ImageReader
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.HandlerThread
import android.util.Log
import android.view.Surface
import android.view.SurfaceHolder
import android.view.View
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.graphics.drawable.toDrawable
import androidx.lifecycle.Observer
import androidx.lifecycle.lifecycleScope
import com.example.android.camera.utils.OrientationLiveData
import com.example.android.camera.utils.getPreviewOutputSize
import com.young.hzh_learning.databinding.ActivityCameraBinding
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine

/**
 * @author huangzehui
 * @date 10/8/2024 上午11:51 周六
 * @description
 */
class CameraActivity : AppCompatActivity() {

    private val TAG = CameraActivity::class.java.simpleName

    private lateinit var activityCameraBinding: ActivityCameraBinding

//    // 第一个后置摄像头
//    private val mBackFormatItem by lazy {
//        CameraUtil.getFirstBackCamera(this)
//    }
//
//    /** Detects, characterizes, and connects to a CameraDevice (used for all camera operations) */
//    private val cameraManager: CameraManager by lazy {
//        val context = applicationContext
//        context.getSystemService(Context.CAMERA_SERVICE) as CameraManager
//    }
//
//    /** [CameraCharacteristics] corresponding to the provided Camera ID */
//    private val characteristics: CameraCharacteristics by lazy {
//        cameraManager.getCameraCharacteristics(mBackFormatItem!!.cameraId)
//    }
//
//    /** Readers used as buffers for camera still shots */
//    private lateinit var imageReader: ImageReader
//
//    /** [HandlerThread] where all camera operations run */
//    private val cameraThread = HandlerThread("CameraThread").apply { start() }
//
//    /** [Handler] corresponding to [cameraThread] */
//    private val cameraHandler = Handler(cameraThread.looper)
//
//    /** Performs recording animation of flashing screen */
//    private val animationTask: Runnable by lazy {
//        Runnable {
//            // Flash white animation
//            activityCameraBinding.overlay.background = Color.argb(150, 255, 255, 255).toDrawable()
//            // Wait for ANIMATION_FAST_MILLIS
//            activityCameraBinding.overlay.postDelayed({
//                // Remove white flash animation
//                activityCameraBinding.overlay.background = null
//            }, CameraActivity.ANIMATION_FAST_MILLIS)
//        }
//    }
//
//    /** [HandlerThread] where all buffer reading operations run */
//    private val imageReaderThread = HandlerThread("imageReaderThread").apply { start() }
//
//    /** [Handler] corresponding to [imageReaderThread] */
//    private val imageReaderHandler = Handler(imageReaderThread.looper)
//
//    /** The [CameraDevice] that will be opened in this fragment */
//    private lateinit var camera: CameraDevice
//
//    /** Internal reference to the ongoing [CameraCaptureSession] configured with our parameters */
//    private lateinit var session: CameraCaptureSession
//
//    /** Live data listener for changes in the device orientation relative to the camera */
//    private lateinit var relativeOrientation: OrientationLiveData

    private val mCameraShowUtil by lazy {
        CameraShowUtil(this, this)
    }

    private var isOpen = true

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        activityCameraBinding = ActivityCameraBinding.inflate(layoutInflater)
        setContentView(activityCameraBinding.root)
        init()

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (!hasPermissions(this)) {
                requestPermissions(PERMISSIONS_REQUIRED, PERMISSIONS_REQUEST_CODE)
            }
        }

        activityCameraBinding.captureButton.setOnClickListener {
            isOpen = !isOpen

            if (isOpen){
                mCameraShowUtil.openCamera()
            } else {
                mCameraShowUtil.closeCamera()
            }

        }

    }

    override fun onRequestPermissionsResult(
        requestCode: Int, permissions: Array<String>, grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == PERMISSIONS_REQUEST_CODE) {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // Takes the user to the success fragment when permission is granted
                mCameraShowUtil.openCamera()
            } else {
                Toast.makeText(this, "Permission request denied", Toast.LENGTH_LONG).show()
            }
        }
    }

    override fun onResume() {
        super.onResume()
        // Before setting full screen flags, we must wait a bit to let UI settle; otherwise, we may
        // be trying to set app to immersive mode before it's ready and the flags do not stick
//        activityCameraBinding.fragmentContainer.postDelayed({
//            activityCameraBinding.fragmentContainer.systemUiVisibility = FLAGS_FULLSCREEN
//        }, IMMERSIVE_FLAG_TIMEOUT)
    }

    override fun onStop() {
        super.onStop()
//        try {
//            camera.close()
//        } catch (exc: Throwable) {
//            Log.e(TAG, "Error closing camera", exc)
//        }
    }

    override fun onDestroy() {
        super.onDestroy()
//        cameraThread.quitSafely()
//        imageReaderThread.quitSafely()
    }

    private fun init(){
        mCameraShowUtil.init(activityCameraBinding.viewFinder)
    }

//    private fun init() {
//        if (mBackFormatItem == null) {
//            return
//        }
//
//        setContentView(activityCameraBinding.root)
//
//        val view = activityCameraBinding.root
//
//        activityCameraBinding.viewFinder.holder.addCallback(object : SurfaceHolder.Callback {
//            override fun surfaceDestroyed(holder: SurfaceHolder) = Unit
//
//            override fun surfaceChanged(
//                holder: SurfaceHolder,
//                format: Int,
//                width: Int,
//                height: Int
//            ) = Unit
//
//            override fun surfaceCreated(holder: SurfaceHolder) {
//                // Selects appropriate preview size and configures view finder
//                val previewSize = getPreviewOutputSize(
//                    activityCameraBinding.viewFinder.display,
//                    characteristics,
//                    SurfaceHolder::class.java
//                )
//                Log.d(
//                    TAG,
//                    "View finder size: ${activityCameraBinding.viewFinder.width} x ${activityCameraBinding.viewFinder.height}"
//                )
//                Log.d(TAG, "Selected preview size: $previewSize")
//                activityCameraBinding.viewFinder.setAspectRatio(
//                    previewSize.width,
//                    previewSize.height
//                )
//
//                // To ensure that size is set, initialize camera in the view's thread
//                view.post { initializeCamera() }
//            }
//        })
//
//        // Used to rotate the output media to match device orientation
//        relativeOrientation = OrientationLiveData(this, characteristics).apply {
//            observe(this@CameraActivity, Observer { orientation ->
//                Log.d(TAG, "Orientation changed: $orientation")
//            })
//        }
//    }
//
//
//    /**
//     * Begin all camera operations in a coroutine in the main thread. This function:
//     * - Opens the camera
//     * - Configures the camera session
//     * - Starts the preview by dispatching a repeating capture request
//     * - Sets up the still image capture listeners
//     */
//    private fun initializeCamera() = lifecycleScope.launch(Dispatchers.Main) {
//        // Open the selected camera
//        camera = openCamera(cameraManager, mBackFormatItem!!.cameraId, cameraHandler)
//
//        // Initialize an image reader which will be used to capture still photos
//        val size = characteristics.get(
//            CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP
//        )!!
//            .getOutputSizes(mBackFormatItem!!.format).maxByOrNull { it.height * it.width }!!
//        imageReader = ImageReader.newInstance(
//            size.width, size.height, mBackFormatItem!!.format, IMAGE_BUFFER_SIZE
//        )
//
//        // Creates list of Surfaces where the camera will output frames
//        val targets = listOf(activityCameraBinding.viewFinder.holder.surface, imageReader.surface)
//
//        // Start a capture session using our open camera and list of Surfaces where frames will go
//        session = createCaptureSession(camera, targets, cameraHandler)
//
//        val captureRequest = camera.createCaptureRequest(
//            CameraDevice.TEMPLATE_PREVIEW
//        ).apply { addTarget(activityCameraBinding.viewFinder.holder.surface) }
//
//        // This will keep sending the capture request as frequently as possible until the
//        // session is torn down or session.stopRepeating() is called
//        session.setRepeatingRequest(captureRequest.build(), null, cameraHandler)
//
//        // Listen to the capture button
//        activityCameraBinding.captureButton.setOnClickListener {
//
//
//        }
//    }
//
//    /** Opens the camera and returns the opened device (as the result of the suspend coroutine) */
//    @SuppressLint("MissingPermission")
//    private suspend fun openCamera(
//        manager: CameraManager,
//        cameraId: String,
//        handler: Handler? = null
//    ): CameraDevice = suspendCancellableCoroutine { cont ->
//        manager.openCamera(cameraId, object : CameraDevice.StateCallback() {
//            override fun onOpened(device: CameraDevice) = cont.resume(device)
//
//            override fun onDisconnected(device: CameraDevice) {
//                Log.w(TAG, "Camera $cameraId has been disconnected")
//                finish()
//            }
//
//            override fun onError(device: CameraDevice, error: Int) {
//                val msg = when (error) {
//                    ERROR_CAMERA_DEVICE -> "Fatal (device)"
//                    ERROR_CAMERA_DISABLED -> "Device policy"
//                    ERROR_CAMERA_IN_USE -> "Camera in use"
//                    ERROR_CAMERA_SERVICE -> "Fatal (service)"
//                    ERROR_MAX_CAMERAS_IN_USE -> "Maximum cameras in use"
//                    else -> "Unknown"
//                }
//                val exc = RuntimeException("Camera $cameraId error: ($error) $msg")
//                Log.e(TAG, exc.message, exc)
//                if (cont.isActive) cont.resumeWithException(exc)
//            }
//        }, handler)
//    }
//
//    /**
//     * Starts a [CameraCaptureSession] and returns the configured session (as the result of the
//     * suspend coroutine
//     */
//    private suspend fun createCaptureSession(
//        device: CameraDevice,
//        targets: List<Surface>,
//        handler: Handler? = null
//    ): CameraCaptureSession = suspendCoroutine { cont ->
//
//        // Create a capture session using the predefined targets; this also involves defining the
//        // session state callback to be notified of when the session is ready
//        device.createCaptureSession(targets, object : CameraCaptureSession.StateCallback() {
//
//            override fun onConfigured(session: CameraCaptureSession) = cont.resume(session)
//
//            override fun onConfigureFailed(session: CameraCaptureSession) {
//                val exc = RuntimeException("Camera ${device.id} session configuration failed")
//                Log.e(TAG, exc.message, exc)
//                cont.resumeWithException(exc)
//            }
//        }, handler)
//    }


    companion object {
        /** Combination of all flags required to put activity into immersive mode */
        const val FLAGS_FULLSCREEN =
            View.SYSTEM_UI_FLAG_LOW_PROFILE or
                    View.SYSTEM_UI_FLAG_FULLSCREEN or
                    View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
                    View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY

        /** Milliseconds used for UI animations */
        const val ANIMATION_FAST_MILLIS = 50L
        const val ANIMATION_SLOW_MILLIS = 100L
        private const val IMMERSIVE_FLAG_TIMEOUT = 500L

        /** Maximum number of images that will be held in the reader's buffer */
        private const val IMAGE_BUFFER_SIZE: Int = 3


        // 权限相关 start
        private const val PERMISSIONS_REQUEST_CODE = 10
        private val PERMISSIONS_REQUIRED = arrayOf(Manifest.permission.CAMERA)

        /** Convenience method used to check if all permissions required by this app are granted */
        fun hasPermissions(context: Context) = PERMISSIONS_REQUIRED.all {
            ContextCompat.checkSelfPermission(context, it) == PackageManager.PERMISSION_GRANTED
        }
        // 权限相关 end


    }
}